package city.spring.modules.system.service.impl;

import city.spring.modules.ext.EntityExtUtils;
import city.spring.modules.ext.entity.*;
import city.spring.modules.ext.service.*;
import city.spring.modules.system.entity.PermissionEntity;
import city.spring.modules.system.entity.RoleEntity;
import city.spring.modules.system.repository.RoleRepository;
import city.spring.modules.system.service.PermissionService;
import city.spring.modules.system.service.RoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 角色信息服务
 *
 * @author HouKunLin
 * @date 2019/12/8 0008 14:55
 */
@CacheConfig(cacheNames = {RoleServiceImpl.CACHE_NAME})
@Transactional(rollbackFor = Throwable.class)
@Service
public class RoleServiceImpl extends ServiceImpl<RoleRepository, RoleEntity> implements RoleService {
    private final PermissionService permissionService;
    private final RolePermissionExtService rolePermissionExtService;
    private final GroupRoleExtService groupRoleExtService;
    private final OrganizationRoleExtService organizationRoleExtService;
    private final UserRoleExtService userRoleExtService;
    private final MenuRoleExtService menuRoleExtService;

    public RoleServiceImpl(PermissionService permissionService, RolePermissionExtService rolePermissionExtService, GroupRoleExtService groupRoleExtService, OrganizationRoleExtService organizationRoleExtService, UserRoleExtService userRoleExtService, MenuRoleExtService menuRoleExtService) {
        this.permissionService = permissionService;
        this.rolePermissionExtService = rolePermissionExtService;
        this.groupRoleExtService = groupRoleExtService;
        this.organizationRoleExtService = organizationRoleExtService;
        this.userRoleExtService = userRoleExtService;
        this.menuRoleExtService = menuRoleExtService;
    }

    @Cacheable(key = "'list:authority:userId:'+#userId")
    @Override
    public List<RoleEntity> getUserRolesWithAuthority(String userId) {
        List<RoleEntity> roles = baseMapper.getUserRoles(userId);
        loadPermissions(roles);
        return roles;
    }

    @Cacheable(key = "'list:authority:groupId:'+#groupId")
    @Override
    public List<RoleEntity> getGroupRolesWithAuthority(String groupId) {
        List<RoleEntity> roles = baseMapper.getGroupRoles(groupId);
        loadPermissions(roles);
        return roles;
    }

    @Cacheable(key = "'list:authority:orgId:'+#orgId")
    @Override
    public List<RoleEntity> getOrganizationRolesWithAuthority(String orgId) {
        List<RoleEntity> roles = baseMapper.getOrganizationRoles(orgId);
        loadPermissions(roles);
        return roles;
    }

    @Override
    public List<RoleEntity> getMenuRolesWithAuthority(String menuId) {
        List<RoleEntity> roles = baseMapper.getMenuRoles(menuId);
        loadPermissions(roles);
        return roles;
    }

    @Cacheable(key = "'list:info:userId:'+#userId")
    @Override
    public List<RoleEntity> getUserRoles(String userId) {
        return baseMapper.getUserRoles(userId);
    }

    @Cacheable(key = "'list:info:groupId:'+#groupId")
    @Override
    public List<RoleEntity> getGroupRoles(String groupId) {
        return baseMapper.getGroupRoles(groupId);
    }

    @Cacheable(key = "'list:info:orgId:'+#orgId")
    @Override
    public List<RoleEntity> getOrganizationRoles(String orgId) {
        return baseMapper.getOrganizationRoles(orgId);
    }

    @Override
    public List<RoleEntity> getMenuRoles(String menuId) {
        return baseMapper.getMenuRoles(menuId);
    }

    @Override
    public void loadPermissions(RoleEntity entity) {
        entity.setPermissions(permissionService.getRolePermissions(entity.getId()));
    }

    @Override
    public void loadPermissions(List<RoleEntity> entities) {
        entities.forEach(this::loadPermissions);
    }

    @Override
    public void saveRole(RoleEntity entity) {
        RoleEntity findEntity = lambdaQuery().eq(RoleEntity::getCode, entity.getCode()).one();
        if (findEntity != null) {
            throw new RuntimeException("已经存在该角色代码");
        }
        entity.setIsSystem(false);
        save(entity);
        // setRolePermission(entity);
    }

    @Override
    public void setRolePermission(RoleEntity entity) {
        // 删除旧的 角色-权限 关联关系  后 再  添加新的关联关系
        EntityExtUtils.repairRelation(rolePermissionExtService, entity,
                RoleEntity::getId, RoleEntity::getPermissions, PermissionEntity::getId,
                RolePermissionExt::new, RolePermissionExt::getRoleId);
    }

    @Override
    public void updateRole(RoleEntity entity) {
        RoleEntity findEntity = lambdaQuery().eq(RoleEntity::getCode, entity.getCode()).one();
        if (findEntity != null && !findEntity.getId().equals(entity.getId())) {
            throw new RuntimeException("已经存在该角色代码");
        }
        entity.setIsSystem(false);
        updateById(entity);
        // setRolePermission(entity);
    }


    @Override
    public void deleteRole(String primaryKey) {
        removeById(primaryKey);
        rolePermissionExtService.lambdaUpdate().eq(RolePermissionExt::getRoleId, primaryKey).remove();
        groupRoleExtService.lambdaUpdate().eq(GroupRoleExt::getRelatedId, primaryKey).remove();
        organizationRoleExtService.lambdaUpdate().eq(OrganizationRoleExt::getRelatedId, primaryKey).remove();
        userRoleExtService.lambdaUpdate().eq(UserRoleExt::getRelatedId, primaryKey).remove();
        menuRoleExtService.lambdaUpdate().eq(MenuRoleExt::getRelatedId, primaryKey).remove();
    }

    @Override
    public void deleteRole(List<String> primaryKeys) {
        removeByIds(primaryKeys);
        rolePermissionExtService.lambdaUpdate().in(RolePermissionExt::getRoleId, primaryKeys).remove();
        groupRoleExtService.lambdaUpdate().in(GroupRoleExt::getRelatedId, primaryKeys).remove();
        organizationRoleExtService.lambdaUpdate().in(OrganizationRoleExt::getRelatedId, primaryKeys).remove();
        userRoleExtService.lambdaUpdate().in(UserRoleExt::getRelatedId, primaryKeys).remove();
        menuRoleExtService.lambdaUpdate().in(MenuRoleExt::getRelatedId, primaryKeys).remove();
    }
}
